#ifndef EXPRESSIONTREE_H_
#define EXPRESSIONTREE_H_

#include "Defines.h"

namespace LALG
{

/*
 * =====================================================================================
 *        Class:  ExpressionTree
 *  Description:  Classe que representa uma árvore de expressões
 * =====================================================================================
 */
class ExpressionTree
{

public:

    /*-----------------------------------------------------------------------------
     *  Constrói uma nova árvore de expressão
     *-----------------------------------------------------------------------------*/
    ExpressionTree() { left = right = NULL; }

    /*-----------------------------------------------------------------------------
     *  Destrói a árvore de expressão
     *-----------------------------------------------------------------------------*/
    virtual ~ExpressionTree()
    {
        if(type == VALUE) delete sval;
        if(type == OPERATOR && left != NULL) delete left;
        if(type == OPERATOR && right != NULL) delete right;
    }

    /*-----------------------------------------------------------------------------
     *  Imprime uma expressão em uma lista
     *-----------------------------------------------------------------------------*/
    void fill(list<string> &lexp) const
    {
        if(type == VALUE)
            lexp.push_back(*sval);
        else if(type == INTEGER)
            lexp.push_back(to_string(ival));
        else if(type == FLOAT)
            lexp.push_back(to_string(fval));
        else
        {
            if(right == NULL)
            {
                lexp.push_back("!");
                left->fill(lexp);
            }
            else
            {
                fillOperator(lexp, op);
                left->fill(lexp);
                right->fill(lexp);
            }
        }
    }

    /*-----------------------------------------------------------------------------
     *  Imprime um operador
     *-----------------------------------------------------------------------------*/
    void fillOperator(list<string> &lexp, int op) const
    {
        if(op == PLUS) lexp.push_back("+");
        else if(op == MINUS) lexp.push_back("-");
        else if(op == TIMES) lexp.push_back("*");
        else if(op == DIVISION) lexp.push_back("/");
        else if(op == EQUAL) lexp.push_back("=");
        else if(op == DIFFERENT) lexp.push_back("<>");
        else if(op == GREATER) lexp.push_back(">");
        else if(op == LESSER) lexp.push_back("<");
        else if(op == GTEQUAL) lexp.push_back(">=");
        else if(op == LEQUAL) lexp.push_back("<=");
    }

    /*-----------------------------------------------------------------------------
     *  Tipo do nó
     *-----------------------------------------------------------------------------*/
    int type;

    /*-----------------------------------------------------------------------------
     *  Valor do nó
     *-----------------------------------------------------------------------------*/
    union
    {
        int op;
        string* sval;
        int ival;
        float fval;
    };

    /*-----------------------------------------------------------------------------
     *  Filho esquerdo
     *-----------------------------------------------------------------------------*/
    ExpressionTree* left;

    /*-----------------------------------------------------------------------------
     *  Filho direito
     *-----------------------------------------------------------------------------*/
    ExpressionTree* right;

};

}

#endif /* EXPRESSIONTREE_H_ */
